#include <iostream>
#include <string>
#include <cstring>
// 引入SVE头文件
#include <arm_sve.h>

using namespace std;

// 定义了Byte，便于使用
typedef unsigned char Byte;
// 定义了32比特
typedef unsigned int bit32;

// MD5的一系列参数。参数是固定的
#define s11 7
#define s12 12
#define s13 17
#define s14 22
#define s21 5
#define s22 9
#define s23 14
#define s24 20
#define s31 4
#define s32 11
#define s33 16
#define s34 23
#define s41 6
#define s42 10
#define s43 15
#define s44 21

/**
 * @Basic MD5 functions for SVE implementation.
 *
 * @param three svuint32_t vectors and a predicate.
 *
 * @return one svuint32_t vector.
 */
#define F_SVE(x, y, z, pg) svorr_z(pg, svand_z(pg, x, y), svand_z(pg, svnot_z(pg, x), z))
#define G_SVE(x, y, z, pg) svorr_z(pg, svand_z(pg, x, z), svand_z(pg, y, svnot_z(pg, z)))
#define H_SVE(x, y, z, pg) sveor_z(pg, sveor_z(pg, x, y), z)
#define I_SVE(x, y, z, pg) sveor_z(pg, y, svorr_z(pg, x, svnot_z(pg, z)))

/**
 * @Rotate Left for SVE.
 *
 * @param {num} the raw number.
 * @param {n} rotate left n.
 * @param {pg} predicate (mask).
 *
 * @return the number after rotated left.
 */
#define ROTATELEFT_SVE(num, n, pg) svorr_z(pg, svlsl_n_u32_z(pg, num, n), svlsr_n_u32_z(pg, num, 32 - n))

#define FF_SVE(a, b, c, d, x, s, ac, pg) { \
  a = svadd_z(pg, a, svadd_z(pg, F_SVE(b, c, d, pg), svadd_z(pg, x, svdup_n_u32_z(pg, ac)))); \
  a = svadd_z(pg, ROTATELEFT_SVE(a, s, pg), b); \
}

#define GG_SVE(a, b, c, d, x, s, ac, pg) { \
  a = svadd_z(pg, a, svadd_z(pg, G_SVE(b, c, d, pg), svadd_z(pg, x, svdup_n_u32_z(pg, ac)))); \
  a = svadd_z(pg, ROTATELEFT_SVE(a, s, pg), b); \
}

#define HH_SVE(a, b, c, d, x, s, ac, pg) { \
  a = svadd_z(pg, a, svadd_z(pg, H_SVE(b, c, d, pg), svadd_z(pg, x, svdup_n_u32_z(pg, ac)))); \
  a = svadd_z(pg, ROTATELEFT_SVE(a, s, pg), b); \
}

#define II_SVE(a, b, c, d, x, s, ac, pg) { \
  a = svadd_z(pg, a, svadd_z(pg, I_SVE(b, c, d, pg), svadd_z(pg, x, svdup_n_u32_z(pg, ac)))); \
  a = svadd_z(pg, ROTATELEFT_SVE(a, s, pg), b); \
}

void SIMD_MD5Hash_8(string input[8], bit32 state[8][4]);
